package org.watchrecords.managers;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.watchrecords.constants.Role;
import org.watchrecords.dbo.User;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;
import com.wideplay.warp.persist.Transactional;
import com.wideplay.warp.persist.dao.Finder;

public class UserManager {
    private Provider<EntityManager> emProvider;
    
    protected UserManager() {}
    
    @Inject
    public UserManager(Provider<EntityManager> emProvider) {
        this.emProvider = emProvider;
    }
    
    /**
     * Ensure that at least one administrator exists
     */
    @Transactional
    public void setup() {
        List<User> admins = getUsersByRole(Role.ADMINISTRATOR);
        
        if (admins.isEmpty()) {
            User admin = new User();
            admin.setName("admin");
            admin.setPassword("admin");
            admin.setRole(Role.ADMINISTRATOR);
            saveUser(admin);
        }
    }
    
    public User getUser(int id) {
        return emProvider.get().find(User.class, id);
    }
    
    @Finder(namedQuery = "getUserByName")
    public User getUser(@Named("username") String username) {
        throw new AssertionError();
    }
    
    public User getUser(@Named("username") String username, @Named("password") String password) {
        try {
            Query query = emProvider.get().createNamedQuery("authenticateUser");
            query.setParameter("username", username);
            query.setParameter("password", password);
            return (User) query.getSingleResult();
        }
        catch (NoResultException e) {
            return null;
        }
    }
    
    @Finder(namedQuery = "getUsersByRole")
    public List<User> getUsersByRole(@Named("role") Role role) {
        throw new AssertionError();
    }

    @Finder(namedQuery = "getUsers")
    public List<User> getUsers() {
        throw new AssertionError();
    }
    
    @Transactional
    public void saveUser(User user) {
        if (user.getId() == null) {
            user.setRegistrationDate(new Date());
        }
        
        emProvider.get().persist(user);
    }
    
    @Transactional
    public void deleteUser(User user) {
        emProvider.get().remove(emProvider.get().merge(user));
    }
}
